/**
 * @class Geometry
 * @description Staticka trieda obsahujuca zakladne operacie nad vektormi
 * a bodmi v rovine.
 *              
 */
var Geometry = {};
Geometry.scalarProduct = scalarProduct;
Geometry.lengthVector = lengthVector;
Geometry.vectorAngle = vectorAngle;
Geometry.pointsToVector = pointsToVector;
Geometry.rotate = rotate;
Geometry.vectorAddition = vectorAddition;
Geometry.unitVector = unitVector;
Geometry.intersectionPoint = intersectionPoint;
Geometry.determinantMatrix = determinantMatrix;
Geometry.layAmong = layAmong;
Geometry.getAxiallySymmetricVector = getAxiallySymmetricVector;
//line
/**
 * @class Line
 * @param A Parameter je bod cez ktory priamka prechadza a/alebo "a" clen 
 * normaloveho vyjadrenia priamky v rovine
 * @param normalVector Parameter je normalovy vektor urcujuci priamku a/alebo "b" clen 
 * normaloveho vyjadrenia priamky v rovine
 * * @param c Parameter je rovny "null" a/alebo "c" clen 
 * normaloveho vyjadrenia priamky v rovine
 * @description Zakladna trieda vektoroveho vyjadrenia priamky v rovne. Parametre bud
 * zvolime A=bod na priamke,normalVector=normalovy vektor priamky,c=null alebo A="a" clen,normalVector="b" clen
 *, c="c" clen.
 */
function Line (A,normalVector,c){
    if (c == null){
        this.a = normalVector.x;
        this.b = normalVector.y;
        this.c = -(this.a*A.x + this.b*A.y);   
    }
    else{
        this.a = A;
        this.b = normalVector;
        this.c = c;
    }
}

// geometry
/**
 * @class Geometry
 * @param u Vektor u
 * @param v Vektor v
 * @description Metoda pocita skalarny sucin vektorov. Vektory sa zadavaj ako obycajne body (trieda Point)
 * @return Vracia skalarny sucin vektorov
 */
function scalarProduct(u,v){
    var result = u.x*v.x+u.y*v.y;
    return result;
}
/**
 * @class Geometry
 * @param v Vektor v
 * @Description Metoda pocita dlzku vektora. Vektory sa zadavaj ako obycajne body (trieda Point).
 * @return dlzka vektora
 */
function lengthVector (v){
    return Math.sqrt((Math.pow(v.x,2))+(Math.pow(v.y,2)));
}
/**
 * @class Geometry
 * @param u Vektor u
 * @param v Vektor v
 * @description Metoda pocita uhol medzi vektormi. Vektory sa zadavaj ako obycajne body (trieda Point)
 * @return Uhol medzi vektormi
 */
function vectorAngle (u,v){
    var result = Math.acos(scalarProduct(u, v)/(lengthVector(v)*lengthVector(u)));
    return (result/Math.PI)*180;
}
/**
 * @class Geometry
 * @param A Bod A
 * @param B Bod B
 * @description Metoda sluziaca na vypocet vektoru AB
 * @return Vracia vektor AB
 */
function pointsToVector (A,B){
    return new Point (B.x-A.x,B.y-A.y);
}
/**
 * @class Geometry
 * @param vector Vektor resp. bod ktory sa bude rotovat.
 * @param angle Uhol o ktory sa bude vektor rotovat
 * @description Metoda sluziaca na rotaciu bodu resp. vektoru
 * @return Varcia bod resp. vektor rotovany o dany uhol
 */
function rotate (vector,angle){
    var angRad = (angle/180)*Math.PI;
    return new Point (vector.x*Math.cos(angRad)-vector.y*Math.sin(angRad),
                                vector.y*Math.cos(angRad)+vector.x*Math.sin(angRad));
}
/**
 * @class Geometry
 * @param A Bod resp vektor
 * @param u vektor
 * @description Metoda sluziaca na posuvanie bodu A vektrom u resp. ako implementacia vektoroveho suctu
 * @return Vracia bod posunuty vektorom resp. vysledok vektoroveho suctu
 */
function vectorAddition (A,u){
    return new Point (A.x+u.x,A.y+u.y);
}
/**
 * @class Geometry
 * @param vector Vektor
 * @description Metoda upravujuca vektor lubovolnej dlzky na vektor jednotkovej dlzky
 * @return Vracia jednotkovy vektor
 */
function unitVector (vector){
    return new Point (vector.x/lengthVector(vector),vector.y/lengthVector(vector));
}
/**
 * @class Geometry
 * @param lineA Parameter typu Line
 * @param lineB Parameter typu Line
 * @description Metoda pocitajuca priesecnik dvoch priamok v priestore
 * @return Vracia priesecnik dvoch priamok, ak priesecnik neexistuje vracia NULL
 */
function intersectionPoint(lineA,lineB){
  var detAB = determinantMatrix(lineA.a,lineA.b,lineB.a,lineB.b);
  var detBC = determinantMatrix(lineA.b,lineA.c,lineB.b,lineB.c);
  var detAC = determinantMatrix(lineB.a,lineB.c,lineA.a,lineA.c);
  if (detAB == 0)
      return null;

  var commonX = detBC/detAB;
  var commonY =detAC/detAB;
  return new Point (commonX,commonY);
}
/**
 * @class Geometry
 * @param a Clen matice 2x2 na pozicii [0,0]
 * @param b Clen matice 2x2 na pozicii [0,1]
 * @param c Clen matice 2x2 na pozicii [1,0]
 * @param d Clen matice 2x2 na pozicii [1,1]
 * @description Implementacia vypoctu determinantu matice rozmerov 2x2
 * @return Vracia hodnotu determinantu matice
 */
function determinantMatrix(a,b,c,d){
    return a*d- b*c;
}
/**
 * @class Geometry
 * @param p bod
 * @param a bod
 * @param b bod
 * @description Metoda zistujuca ci bod p lezi medzi bodmi a a b. Body musia lezat na jednej priamke.
 * @return Vracia True ak bod p lezie medzi ab inak flase
 */
function layAmong (p,a,b){
    var vectAP = pointsToVector (a,p);
    var vectAB = pointsToVector (a,b);
    var det = determinantMatrix(vectAP.x,vectAP.y,vectAB.x,vectAB.y);
    if (Math.round(determinantMatrix(vectAP.x,vectAP.y,vectAB.x,vectAB.y))==0 
            && (lengthVector(vectAP)<lengthVector(vectAB))
            && scalarProduct(vectAB, vectAP)> 0)
        return true;
    
    return false;
}
/**
 * @class Geometry
 * @param vector Vektor
 * @param axialVector Vektor
 * @description Metoda pocitajuca vektor osovo sumerny s priamkou urcenou vektorom axialVector
 * @return Vracia osovo sumerny vector.
 */
function getAxiallySymmetricVector(vector,axialVector){
    var axis = new Line (new Point(0,0),new Point(-axialVector.y,axialVector.x),null);
    var normalV = new Line (vector,axialVector);
    var intersection = intersectionPoint(axis, normalV);
    var transVector = pointsToVector(vector, intersection);
    var result = vectorAddition(vector, new Point (2*transVector.x,2*transVector.y));
    return result;
}